﻿using Microsoft.Office.Interop.Word;
using Microsoft.Win32;
using OpenXMLProcess;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Xps.Packaging;
using Tokenization;
using Utilities;

namespace WPFApplication
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : System.Windows.Window
    {
        MyDocument xml;
        MyDocument xml1;
        Tokenizer tr;
        public MainWindow()
        {
            InitializeComponent();
            xml = new MyDocument();
            xml1 = new MyDocument();
            tr = new Tokenizer();
            docViewer.FitToWidth();
            tr.loadRules("Data/parser_lv_1.xml");
            tr.loadRules("Data/parser_lv_2.xml");
        }

        private void btnOpen_Click(object sender, RoutedEventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();


            // Set filter and RestoreDirectory 
            openFileDialog.RestoreDirectory = true;
            openFileDialog.Filter = "Word documents(*.doc;*.docx)|*.doc;*.docx";

            bool? result = openFileDialog.ShowDialog();
            if (result == true)
            {
                if (openFileDialog.FileName.Length > 0)
                {
                    txtPath.Text = openFileDialog.FileName;
                    if (string.IsNullOrEmpty(txtPath.Text) || !File.Exists(txtPath.Text))
                    {
                        MessageBox.Show("The file is invalid. Please select an existing file again.");
                    }
                    else
                    {
                        string convertedXpsDoc = string.Concat(System.IO.Path.GetTempPath(), "\\", Guid.NewGuid().ToString(), ".xps");
                        XpsDocument xpsDocument = ConvertWordToXps(txtPath.Text, convertedXpsDoc);
                        if (xpsDocument == null)
                        {
                            return;
                        }

                        docViewer.Document = xpsDocument.GetFixedDocumentSequence();
                    }
                }

                xml.Close();
                xml.Open(txtPath.Text);
                xml.ExtractInfo();
            }
        }
        private void btnOpen1_Click(object sender, RoutedEventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();


            // Set filter and RestoreDirectory 
            openFileDialog.RestoreDirectory = true;
            openFileDialog.Filter = "Word documents(*.doc;*.docx)|*.doc;*.docx";

            bool? result = openFileDialog.ShowDialog();
            if (result == true)
            {
                if (openFileDialog.FileName.Length > 0)
                {
                    txtPath1.Text = openFileDialog.FileName;
                    if (string.IsNullOrEmpty(txtPath1.Text) || !File.Exists(txtPath1.Text))
                    {
                        MessageBox.Show("The file is invalid. Please select an existing file again.");
                    }
                    else
                    {
                        string convertedXpsDoc = string.Concat(System.IO.Path.GetTempPath(), "\\", Guid.NewGuid().ToString(), ".xps");
                        XpsDocument xpsDocument = ConvertWordToXps(txtPath1.Text, convertedXpsDoc);
                        if (xpsDocument == null)
                        {
                            return;
                        }

                        docViewer1.Document = xpsDocument.GetFixedDocumentSequence();
                    }
                }

                xml1.Close();
                xml1.Open(txtPath1.Text);
                xml1.ExtractInfo();
            }
        }

        private XpsDocument ConvertWordToXps(string wordFilename, string xpsFilename)
        {
            // Create a WordApplication and host word document 
            Microsoft.Office.Interop.Word.Application wordApp = new Microsoft.Office.Interop.Word.Application();
            try
            {
                wordApp.Documents.Open(wordFilename);

                // To Invisible the word document 
                wordApp.Application.Visible = false;


                // Minimize the opened word document 
                wordApp.WindowState = WdWindowState.wdWindowStateMinimize;


                Document doc = wordApp.ActiveDocument;


                doc.SaveAs(xpsFilename, WdSaveFormat.wdFormatXPS);


                XpsDocument xpsDocument = new XpsDocument(xpsFilename, System.IO.FileAccess.Read);
                return xpsDocument;
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error occurs, The error message is  " + ex.ToString());
                return null;
            }
            finally
            {
                //wordApp.Documents.Close();
                ((_Application)wordApp).Quit(WdSaveOptions.wdDoNotSaveChanges);
            }
        }
        private string[] getWordArray(string para)
        {
            return System.Text.RegularExpressions.Regex.Split(para, "[.,;' ]");
        }
        private string[] getKeyArray(string para)
        {
            string temp = tr.Process(para);
            List<string> rs = new List<string>();
            var tt = System.Text.RegularExpressions.Regex.Matches(temp, @"\[[^\]]+\](?=\[\w+\])");
            foreach (System.Text.RegularExpressions.Match item in tt)
            {
                rs.Add(item.Value);
            }
            return rs.OrderBy(i => i).ToArray();
        }
        private string[] TokenizePara(string temp)
        {
            temp = tr.Process(temp);
            string[] temps = System.Text.RegularExpressions.Regex.Split(temp, "\r\n");
            List<string> ltemp = new List<string>();
            
            foreach (var item in temps)
            {
                try
                {
                    ltemp.Add(System.Text.RegularExpressions.Regex.Split(item, " ||| ")[0]);
                }
                catch (ArgumentOutOfRangeException ex)
                {
                    System.Diagnostics.Debug.WriteLine(ex.Message);
                }
            }
            return ltemp.ToArray();
        }
        private void btnXuLy_Click(object sender, RoutedEventArgs e)
        {
            lbInfo.ItemsSource = null;
            lbInfo.Items.Clear();
            List<InfoListItem> source = new List<InfoListItem>();
            var paras = xml.getAllParagraghs();
            string[] text1, text2;
            Brush background, foreground;
            double r, score = 0;
            switch (tabControl.SelectedIndex)
            {
                case 0:
                    switch (cbbMode.SelectedIndex)
                    {
                        case 0:
                            text2 = getWordArray(txtInput.Text);
                            foreach (var p in paras)
                            {
                                text1 = getWordArray(p.Text);
                                r = Utils._xauChungKhongKe(text1, text2) * 100.0f / (ckbMax.IsChecked.Value ? Math.Max(text1.Length, text2.Length) : Math.Min(text1.Length, text2.Length));
                                r = Math.Round(r, 2);
                                if (r >= 80)
                                {
                                    background = Brushes.Red;
                                    foreground = Brushes.White;
                                }
                                else if (r >= 60 && r < 80)
                                {
                                    background = Brushes.Orange;
                                    foreground = Brushes.Black;
                                }
                                else if (r >= 40 && r < 60)
                                {
                                    background = Brushes.Yellow;
                                    foreground = Brushes.Black;
                                }
                                else if (r >= 20 && r < 40)
                                {
                                    background = Brushes.YellowGreen;
                                    foreground = Brushes.Black;
                                }
                                else
                                {
                                    background = Brushes.White;
                                    foreground = Brushes.Black;
                                }
                                source.Add(new InfoListItem()
                                {
                                    Text = p.Text,
                                    Text1 = txtInput.Text,
                                    Ratio = r,
                                    BackgroundColor = background,
                                    ForegroundColor = foreground
                                });
                            }
                            lbInfo.ItemsSource = source.OrderByDescending(i => i.Ratio).Take(5);
                            break;
                        case 1:
                            text2 = getKeyArray(txtInput.Text);
                            foreach (var p in paras)
                            {
                                text1 = getKeyArray(p.Text);
                                r = Utils._xauChungKhongKe(text1, text2) * 100.0f / (ckbMax.IsChecked.Value ? Math.Max(text1.Length, text2.Length) : Math.Min(text1.Length, text2.Length));
                                if (r >= 80)
                                {
                                    background = Brushes.Red;
                                    foreground = Brushes.White;
                                }
                                else if (r >= 60 && r < 80)
                                {
                                    background = Brushes.Orange;
                                    foreground = Brushes.Black;
                                }
                                else if (r >= 40 && r < 60)
                                {
                                    background = Brushes.Yellow;
                                    foreground = Brushes.Black;
                                }
                                else if (r >= 20 && r < 40)
                                {
                                    background = Brushes.YellowGreen;
                                    foreground = Brushes.Black;
                                }
                                else
                                {
                                    background = Brushes.White;
                                    foreground = Brushes.Black;
                                }
                                source.Add(new InfoListItem()
                                {
                                    Text = p.Text,
                                    Text1 = txtInput.Text,
                                    Ratio = r,
                                    BackgroundColor = background,
                                    ForegroundColor = foreground
                                });
                            }
                            lbInfo.ItemsSource = source.OrderByDescending(i => i.Ratio).Take(5);
                            break;
                    }
                    break;
                case 1:
                    var paras2 = xml1.getAllParagraghs();
                    switch (cbbMode.SelectedIndex)
                    {
                        case 0:
                            foreach (var item in paras2)
                            {
                                text2 = getWordArray(item.Text);
                                foreach (var p in paras)
                                {
                                    text1 = getWordArray(p.Text);
                                    r = Utils._xauChungKhongKe(text1, text2) * 100.0f / (ckbMax.IsChecked.Value ? Math.Max(text1.Length, text2.Length) : Math.Min(text1.Length, text2.Length));
                                    r = Math.Round(r, 2);
                                    if (r >= 80)
                                    {
                                        background = Brushes.Red;
                                        foreground = Brushes.White;
                                    }
                                    else if (r >= 60 && r < 80)
                                    {
                                        background = Brushes.Orange;
                                        foreground = Brushes.Black;
                                    }
                                    else if (r >= 40 && r < 60)
                                    {
                                        background = Brushes.Yellow;
                                        foreground = Brushes.Black;
                                    }
                                    else if (r >= 20 && r < 40)
                                    {
                                        background = Brushes.YellowGreen;
                                        foreground = Brushes.Black;
                                    }
                                    else
                                    {
                                        background = Brushes.White;
                                        foreground = Brushes.Black;
                                    }
                                    source.Add(new InfoListItem()
                                    {
                                        Text = p.Text,
                                        Text1 = item.Text,
                                        Ratio = r,
                                        BackgroundColor = background,
                                        ForegroundColor = foreground
                                    });
                                }
                            }
                            lbInfo.ItemsSource = source.OrderByDescending(i => i.Ratio).Take(5);
                            break;
                        case 1:
                            foreach (var item in paras2)
                            {
                                text2 = getKeyArray(item.Text);
                                foreach (var p in paras)
                                {
                                    text1 = getKeyArray(p.Text);
                                    r = Utils._xauChungKhongKe(text1, text2) * 100.0f / (ckbMax.IsChecked.Value ? Math.Max(text1.Length, text2.Length) : Math.Min(text1.Length, text2.Length));
                                    r = Math.Round(r, 2);
                                    if (r >= 80)
                                    {
                                        background = Brushes.Red;
                                        foreground = Brushes.White;
                                    }
                                    else if (r >= 60 && r < 80)
                                    {
                                        background = Brushes.Orange;
                                        foreground = Brushes.Black;
                                    }
                                    else if (r >= 40 && r < 60)
                                    {
                                        background = Brushes.Yellow;
                                        foreground = Brushes.Black;
                                    }
                                    else if (r >= 20 && r < 40)
                                    {
                                        background = Brushes.YellowGreen;
                                        foreground = Brushes.Black;
                                    }
                                    else
                                    {
                                        background = Brushes.White;
                                        foreground = Brushes.Black;
                                    }
                                    source.Add(new InfoListItem()
                                    {
                                        Text = p.Text,
                                        Text1 = item.Text,
                                        Ratio = r,
                                        BackgroundColor = background,
                                        ForegroundColor = foreground
                                    });
                                }
                            }
                            lbInfo.ItemsSource = source.OrderByDescending(i => i.Ratio).Take(5);
                            break;
                    }
                    foreach (var item in source)
                    {
                        score += item.Ratio;
                    }
                    score /= source.Count;
                    if (score >= 80)
                    {
                        background = Brushes.Red;
                        foreground = Brushes.White;
                    }
                    else if (score >= 60 && score < 80)
                    {
                        background = Brushes.Orange;
                        foreground = Brushes.Black;
                    }
                    else if (score >= 40 && score < 60)
                    {
                        background = Brushes.Yellow;
                        foreground = Brushes.Black;
                    }
                    else if (score >= 20 && score < 40)
                    {
                        background = Brushes.YellowGreen;
                        foreground = Brushes.Black;
                    }
                    else
                    {
                        background = Brushes.White;
                        foreground = Brushes.Black;
                    }
                    txtScore.Background = background;
                    txtScore.Foreground = foreground;
                    txtScore.Content = score + "";
                    break;
                default:
                    break;
            }

        }

        private void lbInfo_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            InfoListItem item = lbInfo.SelectedItem as InfoListItem;
            if (item != null)
            {
                object toolbar = docViewer.Template.FindName("PART_FindToolBarHost", docViewer);

                PropertyInfo contentInfo = toolbar.GetType().GetProperty("Content");
                object findToolbar = contentInfo.GetValue(toolbar, null);

                FieldInfo findTextBoxFieldInfo = findToolbar.GetType().GetField("FindTextBox", BindingFlags.NonPublic | BindingFlags.Instance);
                TextBox findTextBox = (TextBox)findTextBoxFieldInfo.GetValue(findToolbar);

                FieldInfo findNextButtonFieldInfo = findToolbar.GetType().GetField("FindNextButton", BindingFlags.NonPublic | BindingFlags.Instance);
                Button findNextButton = (Button)findNextButtonFieldInfo.GetValue(findToolbar);

                findTextBox.Text = item.Text;
                findNextButton.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
            }
        }

        private void tabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            switch (tabControl.SelectedIndex)
            {
                case 0:
                    panel2.IsEnabled = false;
                    break;
                case 1:
                    panel2.IsEnabled = true;
                    break;
                default:
                    break;
            }
        }

        private void btnSaveTxt_Click(object sender, RoutedEventArgs e)
        {
            Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();
            dlg.FileName = "Document"; // Default file name
            dlg.DefaultExt = ".txt"; // Default file extension
            dlg.Filter = "Text documents (.txt)|*.txt"; // Filter files by extension

            // Show save file dialog box
            Nullable<bool> result = dlg.ShowDialog();

            // Process save file dialog box results
            if (result == true)
            {
                // Save document
                string filename = dlg.FileName;
                using(StreamWriter sw =new StreamWriter(filename))
                {
                    sw.Write(xml.GetText());
                    sw.Close();
                }
            }
        }

        private void btnSaveXML_Click(object sender, RoutedEventArgs e)
        {
            Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();
            dlg.FileName = "Document"; // Default file name
            dlg.DefaultExt = ".txt"; // Default file extension
            dlg.Filter = "Text documents (.txt)|*.txt"; // Filter files by extension

            // Show save file dialog box
            Nullable<bool> result = dlg.ShowDialog();

            // Process save file dialog box results
            if (result == true)
            {
                // Save document
                string filename = dlg.FileName;
                using (StreamWriter sw = new StreamWriter(filename))
                {
                    sw.Write(xml.GetXML());
                    sw.Close();
                }
            }
        }
    }
    class InfoListItem
    {
        public string Text { get; set; }
        public string Text1 { get; set; }
        public double Ratio { get; set; }
        public Brush BackgroundColor { get; set; }
        public Brush ForegroundColor { get; set; }
    }
}
